"use strict";

const Cancel = require("./Cancel");
const utils = require("../utils");

/**
 * “CancelToken”是一个可用于请求取消操作的对象。
 *
 * @class
 * @param {Function} executor 执行器
 */
function CancelToken(executor) {
  if (!utils.isFunction(executor)) {
    throw new TypeError("executor必须是一个函数");
  }

  let resolvePromise;
  this.promise = new Promise(function promiseExecutor(resolve) {
    resolvePromise = resolve;
  });

  const token = this;
  executor(function cancel(message) {
    if (token.reason) {
      // 此时已经要求取消
      return;
    }

    token.reason = new Cancel(message);
    resolvePromise(token.reason);
  });
}

/**
 * 如果请求取消，则抛出“Cancel”。
 */
CancelToken.prototype.throwIfRequested = function throwIfRequested() {
  if (this.reason) {
    throw this.reason;
  }
};

/**
 * 返回一个对象，该对象包含一个新的“CancelToken”和一个函数，该函数在调用时将取消“ CancelToken”。
 */
CancelToken.source = function source() {
  let cancel;
  const token = new CancelToken(function executor(c) {
    cancel = c;
  });
  return {
    token: token,
    cancel: cancel,
  };
};
